function [file] = map_wgs2html(llh, file, opts)
% MAP_WGS2HTML MAP generate HTML file to show WGS84 data in browser
%   [FILE] = MAP_WGS2HTML(LLH, FILE, OPTS) generates html file to display
%   wgs84 positions as track in browser map using Google maps.
%
%   Inputs:
%   LLH     (n, 3) or (n, 2) array of points in GEOD system (WGS84 based)*
%   FILE    opt. name of html file (default: 'wgs.html')
%   OPTS    opt. struct for method options
%   .title  string for browser title (default: 'Track Overview')
%   .header html code of page header (default: ...)
%   .height map height percentage (default: 85)
%   .footer html code of page footer (default: ...)
%   .tcolor string for track color (default: 'cc8000')*
%   .topaci opacity of track polyline (default: 0.5)*
%   .twidth width of track polyline (default: 5)*
%   .beg_nm string for "mouse-over" hint at start marker (default: ...)*
%   .beg_pu html code for "click" popup at start marker (default: ...)*
%   .end_nm string for "mouse-over" hint at end marker (default: ...)*
%   .end_pu html code for "click" popup at end marker (default: ...)*
%
%   *       may also be a cell array of ... to allow for multiple tracks
%           If LLH is a cell array, related OPTS may be defined by single
%           values or cell arrays of same length as the LLH cell array
%
%   Outputs:
%   FILE    name of html file
%
%   Examples:
%   data = [48.786826,9.084312; 48.884134,9.183340]/180*pi;
%   map_wgs2html(data, 'demo.html');
%   web('demo.html', '-browser');
%   generates demo.html in current directory and shows the Solitude
%   trigonometric base line.
%
%   data{1} = [48.786826,9.084312; 48.884134,9.183340]/180*pi;
%   data{2} = [48.786894,9.082922; 48.785995,9.084947]/180*pi;
%   map_wgs2html(data, 'demo.html');
%   web('demo.html', '-browser');
%   generates demo.html with two tracks.
%
%   See also MAP_INTRO.

%   Copyright 2012-2013 OpenCRG - Daimler AG - Jochen Rauh
%
%   Licensed under the Apache License, Version 2.0 (the "License");
%   you may not use this file except in compliance with the License.
%   You may obtain a copy of the License at
%
%       http://www.apache.org/licenses/LICENSE-2.0
%
%   Unless required by applicable law or agreed to in writing, software
%   distributed under the License is distributed on an "AS IS" BASIS,
%   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%   See the License for the specific language governing permissions and
%   limitations under the License.
%
%   More Information on OpenCRG open file formats and tools can be found at
%
%       http://www.opencrg.org
%
%   $Id: map_wgs2html.m 328 2013-05-22 13:06:19Z jorauh $

%% process required args 

lc = iscell(llh);
if lc
    nc = length(llh);
    for ic = 1:nc
        wgs{ic} = llh{ic}(:,1:2)*180/pi; %#ok<AGROW>
    end
else
    nc = 1;
    wgs{1} = llh(:,1:2)*180/pi;
end

%% handle optional args

% FILE

if nargin<2 || isempty(file)
    file = 'wgs.html';
end

% OPTS - single values only

if nargin<3 || isempty(opts)
    opts = struct;
end

if isfield(opts, 'title')
    title = opts.title;
else
    title = 'Track Overview Map';
end

if isfield(opts, 'header')
    header = opts.header;
else
    header = '<h1>Track Overview Map</h1>';
end

if isfield(opts, 'height')
    height = opts.height;
else
    height = 85;
end

if isfield(opts, 'footer')
    footer = opts.footer;
else
    footer = ['<address>generated by ' mfilename ' at ' datestr(now, 31) '</address>'];
end

% OPTS - single value or cell array

if isfield(opts, 'tcolor')
    if iscell(opts.tcolor)
        tcolor = opts.tcolor;
    else
        for ic = 1:nc
            tcolor{ic} = opts.tcolor; %#ok<AGROW>
        end
    end
else
    scolor{1} = '0000ff'; % blue
    scolor{2} = '008000'; % green
    scolor{3} = 'ff0000'; % red
    scolor{4} = '00bfbf'; % cyan
    scolor{5} = 'bf00bf'; % magenta
    scolor{6} = 'bfbf00'; % yellow
    scolor{7} = '3f3f3f'; % grey

    for ic = 1:nc
        tcolor{ic} = scolor{mod(ic-1,length(scolor))+1}; %#ok<AGROW>
    end
end

if isfield(opts, 'topaci')
    if iscell(opts.topaci)
        topaci = opts.topaci;
    else
        for ic = 1:nc
            topaci{ic} = opts.topaci; %#ok<AGROW>
        end
    end
else
    for ic = 1:nc
        topaci{ic} = 0.5; %#ok<AGROW>
    end
end

if isfield(opts, 'twidth')
    if iscell(opts.twidth)
        twidth = opts.twidth;
    else
        for ic = 1:nc
            twidth{ic} = opts.twidth; %#ok<AGROW>
        end
    end
else
    for ic = 1:nc
        twidth{ic} = 5; %#ok<AGROW>
    end
end

if isfield(opts, 'beg_nm')
    if iscell(opts.beg_nm)
        beg_nm = opts.beg_nm;
    else
        for ic = 1:nc
            beg_nm{ic} = opts.beg_nm; %#ok<AGROW>
        end
    end
else
    for ic = 1:nc
        if lc
            beg_nm{ic} = sprintf('Start %u', ic);  %#ok<AGROW>
        else
            beg_nm{ic} = 'Start';  %#ok<AGROW>
        end
    end
end

if isfield(opts, 'beg_pu')
    if iscell(opts.beg_pu)
        beg_pu = opts.beg_pu;
    else
        for ic = 1:nc
            beg_pu{ic} = opts.beg_pu; %#ok<AGROW>
        end
    end
else
    for ic = 1:nc
        if lc
            beg_pu{ic} = sprintf('<h4>Start of Track %u:</h4>', ic); %#ok<AGROW>
        else
            beg_pu{ic} = '<h4>Start of Track:</h4>'; %#ok<AGROW>
        end
        beg_pu{ic} = [beg_pu{ic} '<table style=\"text-align:right\"><tbody>' ...
            '<tr><td>lat =</td><td>' num2str(wgs{ic}(1,1),'%.6f') '</td></tr>' ...
            '<tr><td>lon =</td><td>' num2str(wgs{ic}(1,2),'%.6f') '</td></tr>']; %#ok<AGROW>
        if size(wgs{ic}, 2) > 2
            beg_pu{ic} = [beg_pu{ic} '<tr><td>alt =</td><td>' num2str(wgs{ic}(1,3),'%.6f') '</td></tr>']; %#ok<AGROW>
        end
        beg_pu{ic} = [beg_pu{ic} '</tbody></table>']; %#ok<AGROW>
    end
end

if isfield(opts, 'end_nm')
    if iscell(opts.end_nm)
        end_nm = opts.end_nm;
    else
        for ic = 1:nc
            end_nm{ic} = opts.end_nm; %#ok<AGROW>
        end
    end
else
    for ic = 1:nc
        if lc
            end_nm{ic} = sprintf('End %u', ic);  %#ok<AGROW>
        else
            end_nm{ic} = 'End';  %#ok<AGROW>
        end
    end
end

if isfield(opts, 'end_pu')
    if iscell(opts.end_pu)
        end_pu = opts.end_pu;
    else
        for ic = 1:nc
            end_pu{ic} = opts.end_pu; %#ok<AGROW>
        end
    end
else
    for ic = 1:nc
        if lc
            end_pu{ic} = sprintf('<h4>End of Track %u:</h4>', ic); %#ok<AGROW>
        else
            end_pu{ic} = '<h4>End of Track:</h4>'; %#ok<AGROW>
        end
        end_pu{ic} = [end_pu{ic} '<table style=\"text-align:right\"><tbody>' ...
            '<tr><td>lat =</td><td>' num2str(wgs{ic}(1,1),'%.6f') '</td></tr>' ...
            '<tr><td>lon =</td><td>' num2str(wgs{ic}(1,2),'%.6f') '</td></tr>']; %#ok<AGROW>
        if size(wgs{ic}, 2) > 2
            end_pu{ic} = [end_pu{ic} '<tr><td>alt =</td><td>' num2str(wgs{ic}(1,3),'%.6f') '</td></tr>']; %#ok<AGROW>
        end
        end_pu{ic} = [end_pu{ic} '</tbody></table>']; %#ok<AGROW>
    end
end

%% fill missing cells



%% write html file

fid = fopen(file, 'w');

fprintf(fid, '<!DOCTYPE html>\n');
fprintf(fid, '<html>\n');
fprintf(fid, '  <head>\n');
fprintf(fid, '    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />\n');
fprintf(fid, '    <meta charset="ISO8859-1" />\n');
fprintf(fid, '    <style type="text/css">\n');
fprintf(fid, '      html { height: 100%% } \n');
fprintf(fid, '      body { height: 100%%; margin: 0px; padding: 0px }\n');
fprintf(fid, '      #map_canvas { height: 100%% }\n');
fprintf(fid, '    </style>\n');
fprintf(fid, '    <title>%s</title>\n', title);
fprintf(fid, '    <script type="text/javascript"\n');
fprintf(fid, '            src="https://maps.google.com/maps/api/js?sensor=false">\n');
fprintf(fid, '    </script>\n');
fprintf(fid, '    <script type="text/javascript">\n');
fprintf(fid, '      function initialize() {\n');
fprintf(fid, '        var myOptions = {\n');
fprintf(fid, '          mapTypeId: google.maps.MapTypeId.ROADMAP };\n');
fprintf(fid, '        var map = new google.maps.Map(document.getElementById("map_canvas"),\n');
fprintf(fid, '          myOptions);\n');
fprintf(fid, '        var bounds = new google.maps.LatLngBounds ();\n');

for ic = 1:nc
    fprintf(fid, '        var start%u  = new google.maps.LatLng(%.6f,%.6f);\n', ic, wgs{ic}(1  ,1), wgs{ic}(  1,2));
    fprintf(fid, '        var marker_start%u = new google.maps.Marker({\n', ic);
    fprintf(fid, '          position: start%u,\n', ic);
    fprintf(fid, '          map: map,\n');
    fprintf(fid, '          title: "%s",\n', beg_nm{ic});
    fprintf(fid, '          icon: "http://maps.google.com/mapfiles/dd-start.png"\n');
    fprintf(fid, '          });\n');
    fprintf(fid, '        var beg_pu%u = \n', ic);
    fprintf(fid, '          "%s"\n', beg_pu{ic});
    fprintf(fid, '        var infowindow_start%u = new google.maps.InfoWindow({\n', ic);
    fprintf(fid, '          content: beg_pu%u\n', ic);
    fprintf(fid, '          });\n');
    fprintf(fid, '        google.maps.event.addListener(marker_start%u, "click", function() {\n', ic);
    fprintf(fid, '          infowindow_start%u.open(map,marker_start%u);\n', ic, ic);
    fprintf(fid, '          });\n');
    
    fprintf(fid, '        var end%u    = new google.maps.LatLng(%.6f,%.6f);\n', ic, wgs{ic}(end,1), wgs{ic}(end,2));
    fprintf(fid, '        var marker_end%u = new google.maps.Marker({\n', ic);
    fprintf(fid, '          position: end%u,\n', ic);
    fprintf(fid, '          map: map,\n');
    fprintf(fid, '          title: "%s",\n', end_nm{ic});
    fprintf(fid, '          icon: "http://maps.google.com/mapfiles/dd-end.png"\n');
    fprintf(fid, '          });\n');
    fprintf(fid, '        var end_pu%u = \n', ic);
    fprintf(fid, '          "%s"\n', end_pu{ic});
    fprintf(fid, '        var infowindow_end%u = new google.maps.InfoWindow({\n', ic);
    fprintf(fid, '          content: end_pu%u\n', ic);
    fprintf(fid, '          });\n');
    fprintf(fid, '        google.maps.event.addListener(marker_end%u, "click", function() {\n', ic);
    fprintf(fid, '          infowindow_end%u.open(map,marker_end%u);\n', ic, ic);
    fprintf(fid, '          });\n');
    
    fprintf(fid, '        var polyline%u = [\n', ic);
    for i = 1:size(wgs{ic}, 1)-1
        fprintf(fid, '          new google.maps.LatLng(%.6f,%.6f),\n', wgs{ic}(i,1), wgs{ic}(i,2));
    end
    fprintf(fid, '          new google.maps.LatLng(%.6f,%.6f)];\n', wgs{ic}(end,1), wgs{ic}(end,2));
    
    fprintf(fid, '        var track%u = new google.maps.Polyline({\n', ic);
    fprintf(fid, '          path: polyline%u,\n', ic);
    fprintf(fid, '          strokeColor: "#%s",\n', tcolor{ic});
    fprintf(fid, '          strokeOpacity: %f,\n', topaci{ic});
    fprintf(fid, '          strokeWeight: %d\n', twidth{ic});
    fprintf(fid, '          });\n');
    
    fprintf(fid, '        track%u.setMap(map);\n', ic);
    
    fprintf(fid, '        for (var i = 0, LtLgLen = polyline%u.length; i < LtLgLen; i++) {\n', ic);
    fprintf(fid, '          bounds.extend (polyline%u[i]);\n', ic);
    fprintf(fid, '          }\n');
end

fprintf(fid, '        map.fitBounds (bounds);\n');
fprintf(fid, '      }\n');
fprintf(fid, '      google.maps.event.addDomListener(window, "load", initialize); \n');
fprintf(fid, '    </script>\n');
fprintf(fid, '  </head>\n');

%fprintf(fid, '  <body style="height:95%%; margin:0; font-family:sans-serif" onload="initialize()" onunload="GUnload()">\n');
fprintf(fid, '  <body style="height:95%%; margin:0; font-family:sans-serif" >\n');
fprintf(fid, '    %s\n', header);
fprintf(fid, '    <div id="map_canvas" style="width: 100%%; height: %d%%"></div>\n', height);
fprintf(fid, '    %s\n', footer);
fprintf(fid, '  </body>\n');
fprintf(fid, '</html>\n');

fclose(fid);

end
